package com.bjsxt.controller;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bjsxt.domain.CashWithdrawAuditRecord;
import com.bjsxt.domain.CashWithdrawals;
import com.bjsxt.dto.SellGcnParamDto;
import com.bjsxt.model.Result;
import com.bjsxt.modle.CashWithdrawalsVo;
import com.bjsxt.service.CashWithdrawalsService;
import com.bjsxt.util.ReportCsvUtils;
import com.bjsxt.util.SpringSecurityUtils;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.supercsv.cellprocessor.CellProcessorAdaptor;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.util.CsvContext;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * description:
 * GCN 提现记录控制层
 * TODO: 这里在进行权限配置的时候可能没有对应的权限，以后后期需要统一进行添加
 *
 * @author ALIENWARE
 * @version v1.0.0
 * @create 4/27/2024
 **/
@RestController
@RequestMapping("/cashWithdrawals")
@Api(tags = "GCN 提现记录记录控制器")
public class CashWithdrawalsController {

    /**
     * 自定义状态转换类对象
     */
    public final static CellProcessorAdaptor STATUS_CELL_PROCESSOR_ADAPTOR = new CellProcessorAdaptor() {
        @Override
        public <T> T execute(Object o, CsvContext csvContext) {
            int status = Integer.parseInt(String.valueOf(o));
            String statusStr;
            switch (status) {
                case 0:
                    statusStr = "待审核";
                    break;
                case 1:
                    statusStr = "审核通过";
                    break;
                case 2:
                    statusStr = "拒绝";
                    break;
                case 3:
                    statusStr = "提现成功";
                    break;
                default:
                    statusStr = "未知";
                    break;
            }
            return (T) statusStr;
        }
    };
    /**
     * GCN 提现记录业务层
     */
    @Autowired
    private CashWithdrawalsService cashWithdrawalsService;

    /**
     * 条件分页查询 GCN 提现记录
     *
     * @param page      分页对象<CashWithdrawals>
     * @param userId    用户 ID
     * @param userName  用户名
     * @param mobile    手机号码
     * @param status    状态
     * @param numMin    最小提现金额
     * @param numMax    最大提现金额
     * @param startTime 开始日期
     * @param endTime   结束日期
     * @return 统一响应对象
     */
    @GetMapping("/records")
    // @PreAuthorize("hasAuthority('trade_coin_type_query')")
    @ApiOperation(value = "条件分页查询 GCN 提现记录", authorizations = {@Authorization("Authorization")})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页", dataType = "Long", paramType = "query", example = "1"),
            @ApiImplicitParam(name = "size", value = "每页条数", dataType = "Long", paramType = "query", example = "20"),
            @ApiImplicitParam(name = "userId", value = "用户 ID", dataType = "Long", paramType = "query", example = "9001"),
            @ApiImplicitParam(name = "userName", value = "用户名", dataType = "String", paramType = "query", example = "张三"),
            @ApiImplicitParam(name = "mobile", value = "手机号码", dataType = "String", paramType = "query", example = "13517765487"),
            @ApiImplicitParam(name = "status", value = "状态", dataType = "Byte", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "numMin", value = "最小提现金额", dataType = "Integer", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "numMax", value = "最大提现金额", dataType = "Long", paramType = "query", example = "100"),
            @ApiImplicitParam(name = "startTime", value = "开始日期", dataType = "Long", paramType = "query", example = "1970-01-01"),
            @ApiImplicitParam(name = "endTime", value = "结束日期", dataType = "Long", paramType = "query", example = "1970-01-02")
    })
    public Result<Page<CashWithdrawalsVo>> findByPage(@ApiIgnore Page<CashWithdrawals> page, Long userId, String userName, String mobile, Byte status, Integer numMin, Integer numMax, @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime) {
        page.addOrder(OrderItem.desc(CashWithdrawals.COL_LAST_UPDATE_TIME));
        // 调用业务层进行分页数据的查询
        Page<CashWithdrawalsVo> cashWithdrawalsPage = cashWithdrawalsService.pageByUserIdAndUserNameAndMobileAndStatusAndNumAndCreateTime(page, userId, userName, mobile, status, numMin, numMax, startTime, endTime);
        // 返回响应数据
        return Result.success(cashWithdrawalsPage);
    }

    /**
     * 查询用户的 GCN 提现记录
     *
     * @param page   分页对象<CashWithdrawals>
     * @param status 状态：状态：0-待审核；1-审核通过；2-拒绝；3-提现成功；
     * @return 统一响应对象
     */
    @GetMapping("/user/records")
    @ApiOperation(value = "查询用户的 GCN 提现记录", authorizations = {@Authorization("Authorization")})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页", dataType = "Long", paramType = "query", example = "1"),
            @ApiImplicitParam(name = "size", value = "每页条数", dataType = "Long", paramType = "query", example = "20"),
            @ApiImplicitParam(name = "status", value = "状态：0-待审核；1-审核通过；2-拒绝；3-提现成功；", dataType = "Byte", paramType = "query", example = "0991")
    })
    public Result<Page<CashWithdrawals>> findUserByPage(@ApiIgnore Page<CashWithdrawals> page, Byte status) {
        // 获取当前登录人的用户 id
        Long userId = SpringSecurityUtils.getCurrentUserId();
        // 根据用户 id 分页查询 GCN 充值记录
        Page<CashWithdrawals> cashWithdrawalsPage = cashWithdrawalsService.pageByUserIdAndStatus(page, userId, status);
        // 返回响应数据
        return Result.success(cashWithdrawalsPage);
    }

    /**
     * GCN 的提现
     *
     * @param sellGcnParamDto 提现 GCN 传输类对象
     * @return 统一响应对象
     */
    @PostMapping("/sell")
    // @PreAuthorize("hasAuthority('trade_coin_type_query')")
    @ApiOperation(value = "GCN 的提现", authorizations = {@Authorization("Authorization")})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "coinId", value = "币种的 id", dataType = "Long", required = true, paramType = "query", example = "1"),
            @ApiImplicitParam(name = "num", value = "提现币种的数量", dataType = "String", required = true, paramType = "query", example = "0"),
            @ApiImplicitParam(name = "mun", value = "提现币种的金额", required = true, dataType = "Byte", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "payPassword", value = "支付密码", required = true, dataType = "Byte", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "validateCode", value = "验证码", required = true, dataType = "Byte", paramType = "query", example = "0")
    })
    public Result<Void> sellGcn(@RequestBody @Validated SellGcnParamDto sellGcnParamDto) {
        // 获取当前用户的 id
        Long userId = SpringSecurityUtils.getCurrentUserId();
        // 调用业务层代码进行提现操作
        boolean flag = cashWithdrawalsService.sellGcn(userId, sellGcnParamDto);
        // 如果为 true 更新成功
        if (flag) return Result.success("提现成功");
        // 如果为 false 更新失败
        return Result.fail("提现失败");
    }

    /**
     * 现金提现审核
     *
     * @param cashWithdrawAuditRecord 提现审核记录
     * @return 统一响应对象
     */
    @PostMapping("/updateStatus")
    // @PreAuthorize("hasAuthority('trade_coin_type_query')")
    @ApiOperation(value = "现金充值审核", authorizations = {@Authorization("Authorization")})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "充值订单的 ID", dataType = "Long", required = true, paramType = "query", example = "1"),
            @ApiImplicitParam(name = "remark", value = "审核的建议，备注", dataType = "String", required = true, paramType = "query", example = "0"),
            @ApiImplicitParam(name = "status", value = "审核的状态：0-待审核；1-审核通过；2-拒绝；3-审核成功；", required = true, dataType = "Byte", paramType = "query", example = "0")
    })
    public Result<Void> updateStatus(@RequestBody CashWithdrawAuditRecord cashWithdrawAuditRecord) {
        // 获取审核的用户 id
        Long userId = SpringSecurityUtils.getCurrentUserId();
        // 调用业务层方法进行数据的更新
        boolean flag = cashWithdrawalsService.cashRechargeAudit(userId, cashWithdrawAuditRecord);
        // 如果为 true 审核成功
        if (flag) return Result.success("审核成功");
        // 如果为 false 审核失败
        return Result.fail("审核失败");
    }

    /**
     * 导出 GCN 提现记录，导出的文件格式为 CSV 文件
     *
     * @param userId    用户 ID
     * @param userName  用户名
     * @param mobile    手机号码
     * @param status    状态
     * @param numMin    最小提现金额
     * @param numMax    最大提现金额
     * @param startTime 开始日期
     * @param endTime   结束日期
     * @param response  请求响应对象
     * @return 统一响应对象
     */
    @GetMapping("/exportCashWithdrawals")
    // @PreAuthorize("hasAuthority('trade_coin_type_query')")
    @ApiOperation(value = "导出 GCN 提现记录，导出的文件格式为 CSV 文件", authorizations = {@Authorization("Authorization")})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户 ID", dataType = "Long", paramType = "query", example = "9001"),
            @ApiImplicitParam(name = "userName", value = "用户名", dataType = "String", paramType = "query", example = "张三"),
            @ApiImplicitParam(name = "mobile", value = "手机号码", dataType = "String", paramType = "query", example = "13517765487"),
            @ApiImplicitParam(name = "status", value = "状态", dataType = "Byte", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "numMin", value = "最小提现金额", dataType = "Integer", paramType = "query", example = "0"),
            @ApiImplicitParam(name = "numMax", value = "最大提现金额", dataType = "Long", paramType = "query", example = "100"),
            @ApiImplicitParam(name = "startTime", value = "开始日期", dataType = "Long", paramType = "query", example = "1970-01-01"),
            @ApiImplicitParam(name = "endTime", value = "结束日期", dataType = "Long", paramType = "query", example = "1970-01-02")
    })
    public void exportCashWithdrawals(Long userId, String userName, String mobile, Byte status, Integer numMin, Integer numMax, @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime, HttpServletResponse response) {
        // 创建分页对象
        Page<CashWithdrawals> page = new Page<>(1, 1000);
        // 增加排序条件
        page.addOrder(OrderItem.desc(CashWithdrawals.COL_LAST_UPDATE_TIME));
        // 调用业务层进行分页数据的查询
        Page<CashWithdrawalsVo> cashWithdrawalsPage = cashWithdrawalsService.pageByUserIdAndUserNameAndMobileAndStatusAndNumAndCreateTime(page, userId, userName, mobile, status, numMin, numMax, startTime, endTime);
        // 表格列
        String[] header = {"ID", "用户ID", "用户名", "提现金额(USDT)", "手续费", "到账金额", "提现开户名", "银行名称", "账户", "申请时间", "完成时间", "状态", "备注", "审核级数"};
        // 获取的数据属性
        String[] properties = {"id", "userId", "username", "num", "fee", "mum", "truename", "bank", "bankCard", "created", "lastTime", "status", "remark", "step"};
        CellProcessor[] cellProcessors = new CellProcessor[]{
                ReportCsvUtils.LONG_TO_STRING_PROCESSORS, ReportCsvUtils.LONG_TO_STRING_PROCESSORS, null, //"ID", "用户ID", "用户名",
                ReportCsvUtils.BIG_DECIMAL_TO_STRING8, ReportCsvUtils.BIG_DECIMAL_TO_STRING8, ReportCsvUtils.BIG_DECIMAL_TO_STRING8, // "提现金额(USDT)", "手续费", "到账金额",
                null, null, null,//"提现开户名", "银行名称, 账号"
                ReportCsvUtils.DATE_TO_STRING_PROCESSORS, ReportCsvUtils.DATE_TO_STRING_PROCESSORS, //  "申请时间", "完成时间"
                STATUS_CELL_PROCESSOR_ADAPTOR, // 状态
                null, null // 备注 审核级数
        };
        // 导出 csv 文件
        try {
            ReportCsvUtils.reportListCsv(response, header, properties, "GCN 提现记录.csv", cashWithdrawalsPage.getRecords(), cellProcessors);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}